package com.xbongbong.paas.toolbox.wrap;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.annotation.JSONField;
import com.xbongbong.paas.toolbox.pojo.DataPermissionParamsPojo;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.sys.enums.RoleEnum;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.beans.Transient;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;


/**
 * 用户VO，目前主要用于用户列表接口
 * @author kaka
 * @time 2018-9-4 9:20
 */
@Getter
@Setter
@ToString
public class UserVO implements Serializable {

    private static final long serialVersionUID = -1935053056478122874L;

    /**
     * 用户自增主键，一般不参与业务逻辑
     */
    private Integer id;

    /**
     * 用户所在公司id
     */
    private String corpid;

    /**
     * 用户id，参与逻辑的用户标示
     */
    private String userId;

    /**
     * 钉钉id
     */
    private String dingId;

    /**
     * 用户姓名
     */
    private String name;

    /**
     * 职位信息
     */
    private String position;

    /**
     * 头像url
     */
    private String avatar;

    /**
     * 所在的部门列表"[1,2,3]"
     */
    private String department;

    /**
     * 该用户具有的角色列表，|roleId1|roleId2|格式
     */
    private String roleIds;

    /**
     * 0 表示正常在职，1 表示离职，2 表示不可见
     */
    private Integer del;

    /**
     * 	在对应的部门中是否为主管, Map结构的json字符串, key是部门的Id, value是人员在这个部门中是否为主管,
     * 	true表示是, false表示不是."{1:true, 2:false}"
     */
    private String isLeaderInDepts;

    /**
     * 用户具有的角色列表
     */
    private Set<RoleSimpleVO> roleSet;

    /**
     * 用户所在的部门列表
     */
    private Set<DepartmentVO> depSet;

    /**
     * saas权限，alias
     */
    private Set<String> permSet;

    /**
     * 动态权限，alias
     */
    private Set<String> dynamicPermSet;

    /**
     * 员工所在部门名通过英文逗号(,)连接
     */
    private String departmentConcat;

    /**
     * 员工所具有的角色名通过英文逗号(,)连接
     */
    private String roleConcat;

    /**
     * 该员工最高权限
     */
    private Integer dataPermission;

    /**
     * 多个角色paasPermissions的并集
     */
    private String paasPermissions;
    /**
     * 客户查重权限
     */
    private boolean customerDuplicate;
    /**
     * 线索查重权限
     */
    private boolean clueDuplicate;
    /**
     * 联系人查重权限
     */
    private boolean contactDuplicate;
    /**
     * 精确到表单级的数据权限，{
     *   "1_100":1,
     *   "2_33":4,
     *   ...
     * }
     * 格式说明：
     * key值格式为：
     * SaaS：saaSMark_businessType
     * PaaS：saasMark_menuid
     * value值为：各个角色的数据权限聚合，为各自表单的最高权限
     * 特殊说明：组织权限的数据权限的key值为：1_0（因为没有自己的表单）
     */
    private Map<String, Integer> dataPermissionDetail;
    /**
     * 手机号
     */
    private String mobile;
    /**
     * 邮箱
     */
    private String email;

    /**
     * 企微二维码URL
     */
    private String QRCode;

    /**
     * 标签
     */
    private JSONArray labels;

    /**
     * 标签
     */
    private List<LabelVO> labelSet;


    /**
     * 判断当前user是否是管理员或老板，即是否符合roleIds包含|1|或|2|，这个判断与全公司权限datapermission=5不一样
     * @return true 是， false 否
     */
    @Transient
    public boolean isAdminOrBoss() {
        return isAdmin() || isBoss();
    }

    /**
     * 判断当前user是否是管理员，即是否符合roleIds包含|1|，这个判断与全公司权限datapermission=5不一样
     * @return true 是， false 否
     */
    @Transient
    public boolean isAdmin() {
        return this.roleIds != null && this.roleIds.contains(RoleEnum.ADMIN.getAlias());
    }

    /**
     * 判断当前user是否是老板，即是否符合roleIds包含|2|，这个判断与全公司权限datapermission=5不一样
     * @return true 是， false 否
     */
    @Transient
    public boolean isBoss() {
        return this.roleIds != null && this.roleIds.contains(RoleEnum.BOSS.getAlias());
    }

    /**
     * 工单（首页抢单工单关闭权限）
     * 判断user是否是管理员、老板或工单主管
     *
     * @return boolean true 是，false 否
     * @author 徐俊杰
     * @date 2019/7/6 10:44
     * @since v1.0
     */
    @Transient
    public boolean isAdminOrBossOrWorkOrderManager() {
        return (this.roleIds != null) && (isAdminOrBoss() || this.roleIds.contains(RoleEnum.WORKORDER_MANAGER.getAlias()));
    }

    /**
     * 工单（首页抢单工单关闭权限）
     * 判断user是否是工单主管
     *
     * @return boolean true 是，false 否
     * @author 徐斌
     * @date 2020/5/19 19:24
     * @since v1.0
     */
    @Transient
    public boolean isWorkOrderManager() {
        return (this.roleIds != null) && (this.roleIds.contains(RoleEnum.WORKORDER_MANAGER.getAlias()));
    }

    /**
     * 工单（首页抢单工单关闭权限）
     * 判断user是否是销售主管
     *
     * @return boolean true 是，false 否
     * @author 徐斌
     * @date 2020/5/19 19:24
     * @since v1.0
     */
    @Transient
    public boolean isManager() {
        return (this.roleIds != null) && (this.roleIds.contains(RoleEnum.MANAGER.getAlias()));
    }

    /**
     * 工单（首页抢单工单关闭权限）
     * 判断user是否是采购主管
     *
     * @return boolean true 是，false 否
     * @author 徐斌
     * @date 2020/5/19 19:24
     * @since v1.0
     */
    @Transient
    public boolean isPurchaseManager() {
        return (this.roleIds != null) && (this.roleIds.contains(RoleEnum.PURCHASE_MANAGER.getAlias()));
    }

    /**
     * 判断该用户具有的最高数据权限是否为全公司权限，也可以使用com.xbongbong.sys.util.UserPermissionUtil#isMaxDataPermission(com.xbongbong.paas.toolbox.wrap.UserVO, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Long, boolean)
     * @return 若有全公司权限则返回 true, 否则返回false
     */
    @JSONField(serialize = false)
    @Transient
    public boolean isMaxDataPermission() {
        return isMaxDataPermission(false);
    }

    @JSONField(serialize = false)
    @Transient
    public boolean isMaxDataPermission(boolean isOrganization) {
        Integer permission = null;
        if (isOrganization) {
            permission = dataPermissionDetail.get(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.SYSTEM.getCode());
        } else {
            DataPermissionParamsPojo dataPermissionParamsPojoValue = TransmittableThreadLocalUtil.getDataPermissionParamsPojoValue();
            SaasMarkEnum saasMarkEnum = SaasMarkEnum.getMemo(dataPermissionParamsPojoValue.getSaasMark());
            Integer businessType = XbbRefTypeEnum.transferBusinessType4Distributor(dataPermissionParamsPojoValue.getBusinessType(), dataPermissionParamsPojoValue.getDistributorMark());
            //出库发货单没有单独的menu和销售出库单共用
            if (Objects.equals(businessType,XbbRefTypeEnum.ORDER_OUTSTOCK.getCode())){
                businessType = XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode();
            }
            // 日报、周报、月报需要转换成工作报告
//            if (Objects.equals(businessType, XbbRefTypeEnum.WORKREPORT_DAILY.getCode()) ||
//                Objects.equals(businessType, XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode()) ||
//                Objects.equals(businessType, XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode())) {
//                businessType = XbbRefTypeEnum.WORK_REPORT.getCode();
//            }
            Long menuId = dataPermissionParamsPojoValue.getMenuId();
            String key;
            if (!Objects.isNull(saasMarkEnum)) {
                switch (saasMarkEnum) {
                    case SAAS:
                        key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + businessType;
                        permission = dataPermissionDetail.get(key);
                        break;
                    case PAAS:
                        key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + menuId;
                        permission = dataPermissionDetail.get(key);
                        break;
                    case THIRD_PARTY:
                        break;
                    default:
                        throw new IllegalStateException("Unexpected value: " + saasMarkEnum);
                }
            }
        }
        return permission != null && permission.equals(5);
    }

    public UserVO() {
        this.permSet = new HashSet<>();
    }

    public Set<String> getDynamicPermSet() {
        if (Objects.isNull(dynamicPermSet)) {
            dynamicPermSet = new HashSet<>();
        }
        return dynamicPermSet;
    }
}
